#pragma once
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
#include <cerrno>
#include <cstdlib>
#include "Log.hpp"
#include "Common.hpp"
using namespace LogMoudle;
namespace SocketMoudle
{
    const static int defaulted = -1;
    class Socket
    {
        // 基类套接字
    public:
        Socket() : _sockfd(defaulted) {}
        Socket(int sockfd) : _sockfd(sockfd) {}
        virtual int SocketOrDie() = 0;
        virtual bool BindOrDie(uint16_t port) = 0;
        virtual bool ListenOrDie(int backlog = 10) = 0;
        // virtual std::shared_ptr<Socket> Accept(NetAddr*client) = 0;
        virtual int Accept(NetAddr *client) = 0;
        virtual int Recv(std::string *in) = 0;
        virtual void Close() = 0;
        virtual bool Send(const std::string &out) = 0;
        virtual int Connect(std::string &ip, uint16_t port) = 0;
        void BuildclientSocket(std::string &ip, uint16_t port)
        {
            // 创建套接字
            SocketOrDie();
        }
        virtual int GetSockFd() { return _sockfd; }

    public:
        void BuildListenSocket(uint16_t port, int backlog = 10)
        {
            SocketOrDie();
            BindOrDie(port);
            ListenOrDie(backlog);
        }
        void BuildUdpSocket(uint16_t port, int backlog = 10)
        {
            SocketOrDie();
            BindOrDie(port);
        }

    private:
        int _sockfd; // listenfd,sockfd
    };
    class TcpSocket : public Socket
    {
    public:
        TcpSocket(int sockfd) : _sockfd(sockfd) {};
        TcpSocket() : _sockfd(defaulted) {};
        TcpSocket(std::string &ip, uint16_t port) { BuildclientSocket(ip, port); }
        int SocketOrDie() override
        {            // 创建套接字      
            _sockfd = socket(AF_INET, SOCK_STREAM, 0);
            if (_sockfd < 0)
            {
                LOG(LogLevel::ERROR) << "套接字创建失败";
                exit(1);
            }
            LOG(LogLevel::INFO) << "套接字创建成功";
            return 0;
        }
        int Connect(std::string &ip, uint16_t port) override
        {
            NetAddr server(ip, port);
            return connect(_sockfd, (struct sockaddr *)&server.getAddr(), server.getAddrLen());
        }
        ~TcpSocket() {}
        bool BindOrDie(uint16_t port) override
        {
            NetAddr _addr(port);
            int ret = bind(_sockfd, (struct sockaddr *)&_addr.getAddr(), _addr.getAddrLen());
            if (ret < 0)
            {
                LOG(LogLevel::ERROR) << "套接字绑定失败";
                return false;
            }
            LOG(LogLevel::INFO) << "套接字绑定成功";
            return true;
        }
        bool ListenOrDie(int backlog = 10) override
        {
            int ret = listen(_sockfd, backlog);
            if (ret < 0)
            {
                LOG(LogLevel::ERROR) << "套接字监听失败";
                return false;
            }
            LOG(LogLevel::INFO) << "套接字监听成功";
            return true;
        };
        // std::shared_ptr<Socket> Accept(NetAddr*client)override
#define ACCEPT_ERROR -3
#define ACCEPT_DONE -1
#define ACCEPT_CONTINUE -2
        int Accept(NetAddr *client) override
        {
            struct sockaddr_in client_addr;
            socklen_t client_len = sizeof(client_addr);
            int fd = accept(_sockfd, (struct sockaddr *)&client_addr, &client_len);
            if (fd < 0)
            {
                if (errno == EINTR || errno == EWOULDBLOCK)
                {
                    return -1;
                }
                else if (errno == EINTR)
                {
                    return -2;
                }
                else
                {
                    LOG(LogLevel::ERROR) << "accept error";
                    return -3; // 读取出错
                }
            }
            client->SetAddr(client_addr);
            return fd;
        };
        void Close() override
        {
            if (_sockfd > 0)
                close(_sockfd);
        }
        int Recv(std::string *in) override
        {
            char buffer[4096 * 2];
            ssize_t n = recv(_sockfd, buffer, sizeof(buffer) - 1, 0);
            // if(n < 0){
            //     if(errno==EINTR||errno==EAGAIN){
            //         return "";
            //     }
            //     LOG(LogLevel::ERROR)<<"接收数据失败";
            //     return false;
            // }else if(n==0){
            //     LOG(LogLevel::INFO)<<"客户端断开连接";
            //     return false;
            // }
            if (n > 0)
            {
                buffer[n] = 0;
                *in += buffer;
            }
            return n;
        };
        bool Send(const std::string &out) override
        {
            ssize_t n = send(_sockfd, out.c_str(), out.size(), 0);
            if (n < 0)
            {
                if (errno == EINTR || errno == EAGAIN)
                {
                    return "";
                }
                LOG(LogLevel::ERROR) << "发送数据失败";
                return false;
            }
            else if (n == 0)
            {
                LOG(LogLevel::INFO) << "客户端断开连接";
                return false;
            }
            return true;
        }
        int GetSockFd() override { return _sockfd; }

    private:
        int _sockfd; // listenfd,sockfd
    };
    // class UdpSocket:public Socket{

    // };
}